import { WechatyBuilder } from "wechaty";
import qrcode_terminal from "qrcode-terminal";
import config from "@/utils/config";
import ernieService from "./ernieService";
import utils from "@/utils/utils";
import log4js from "@/utils/log4js";

const logger = utils;

class WeChatBot {
  constructor() {
    this.bot = WechatyBuilder.build({
      name: config.bot.name,
      puppet: "wechaty-puppet-wechat4u",
    });

    this.groupConfigs = new Map();
    this.conversations = new Map();
    this.isRunning = false;
    this.messageQueue = new MessageQueue();

    this.initialize();
  }

  async errorHandler(func, ...args) {
    try {
      return await func.apply(this, args);
    } catch (error) {
      logger.fail("操作错误:", error);
      return null;
    }
  }

  initialize() {
    this.setupEventHandlers();
  }

  setupEventHandlers() {
    this.bot
      .on("scan", this.handleScan.bind(this))
      .on("login", this.handleLogin.bind(this))
      .on("logout", this.handleLogout.bind(this))
      .on("message", this.handleMessage.bind(this))
      .on("error", this.handleError.bind(this));
  }

  handleScan(qrcode, status) {
    qrcode_terminal.generate(qrcode, { small: true });
    const qrcodeUrl = `https://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`;
    const message = `[${status}] 请扫描二维码登录: ${qrcodeUrl}`;
    logger.success(message);
    log4js.info(message);
  }

  async handleLogin(user) {
    logger.success(`${user.name()} 登录成功`);
    this.isRunning = true;
    await this.setupGroups();
  }

  handleLogout(user, reason) {
    logger.success(`${user.name()} 登出，原因: ${reason}`);
    this.isRunning = false;
    this.handleLogout();
  }

  getContextSummary(roomId, userId) {
    const context = this.getContext(roomId, userId);
    return ernieService.getContextSummary(context);
  }

  async handleMessage(msg) {
    if (msg.self() || !msg.room()) return;

    try {
      const room = msg.room();
      const roomId = await room.id;
      if (!this.groupConfigs.has(roomId)) return;

      const sender = msg.talker();
      if (!sender) {
        logger.warn("无法获取发送者信息");
        return;
      }

      const isMentioned = await this.errorHandler(async () => msg.mentionSelf());
      if (!isMentioned) return;

      const text = await this.extractMessageText(msg);
      if (!text) return;

      logger.success(`收到消息: ${text} (from: ${sender.name()})`);

      if (text.startsWith("/")) {
        await this.handleCommand(room, sender, text);
        return;
      }

      await this.processMessage(room, sender, text, roomId);
    } catch (error) {
      logger.fail("消息处理错误:", error);
      await this.handleMessageError(msg.room(), error);
    }
  }

  async processMessage(room, sender, text, roomId) {
    await this.checkRateLimit(roomId);
    const context = this.getContext(roomId, sender.id);

    try {
      const { reply, context: newContext } = await ernieService.chat(text, context);
      if (!reply) {
        logger.warn("API 返回空回复");
        return;
      }

      this.saveContext(roomId, sender.id, newContext);
      await this.sendResponse(room, sender, reply);
    } catch (error) {
      logger.fail("调用 API 失败:", error);
      await this.messageQueue.add(room, "抱歉，系统暂时出现问题，请稍后再试。");
    }
  }

  async handleMessageError(room, error) {
    const message = error.message.includes("频率限制") 
      ? "消息太快啦，请稍后再试~"
      : "抱歉，系统暂时出现问题，请稍后再试。";
    await this.messageQueue.add(room, message);
  }

  async extractMessageText(msg) {
    try {
      const text = msg.text();
      const botName = this.bot.name();
      return text.replace(new RegExp(`@${botName}\\s*`, "g"), "").trim();
    } catch (error) {
      logger.fail("提取消息文本错误:", error);
      return "";
    }
  }

  async handleCommand(room, sender, text) {
    const [command, ...args] = text.slice(1).split(" ");

    try {
      const commands = {
        help: async () => {
          await this.messageQueue.add(
            room,
            `@${sender.name()}\n支持的命令：
  /help - 显示此帮助信息
  /clear - 清除上下文
  /stats - 显示统计信息
  /context - 显示当前对话上下文信息`
          );
        },
        clear: async () => {
          this.clearContext(room.id, sender.id);
          await this.messageQueue.add(room, `@${sender.name()} 已清除上下文记忆`);
        },
        context: async () => {
          const summary = this.getContextSummary(room.id, sender.id);
          await this.messageQueue.add(
            room,
            `@${sender.name()}\n上下文信息：
  消息数量: ${summary.messageCount}
  最后消息: ${summary.lastMessage ? summary.lastMessage.content.substring(0, 50) + "..." : "无"}
  总字数: ${summary.totalLength}`
          );
        },
        stats: async () => {
          const stats = await this.getStats(room);
          await this.messageQueue.add(room, `@${sender.name()}\n${stats}`);
        }
      };

      const commandHandler = commands[command.toLowerCase()];
      if (commandHandler) {
        await commandHandler();
      } else {
        await this.messageQueue.add(room, `@${sender.name()} 未知命令，输入 /help 查看帮助`);
      }
    } catch (error) {
      logger.fail("处理命令错误:", error);
      await this.messageQueue.add(room, "命令执行失败，请稍后重试");
    }
  }

  async checkRateLimit(roomId) {
    const config = this.groupConfigs.get(roomId);
    if (!config) return;

    const now = Date.now();
    const { rateLimit } = config;

    if (now - rateLimit.lastReset > 60000) {
      rateLimit.count = 0;
      rateLimit.lastReset = now;
    }

    if (rateLimit.count >= rateLimit.maxPerMinute) {
      throw new Error("频率限制");
    }

    rateLimit.count++;
  }

  async setupGroups() {
    try {
      const roomList = await this.bot.Room.findAll();

      for (const room of roomList) {
        const topic = await room.topic();
        const roomId = await room.id;

        this.groupConfigs.set(roomId, {
          name: topic,
          rateLimit: {
            count: 0,
            lastReset: Date.now(),
            maxPerMinute: config.bot.rateLimitPerMinute,
          },
        });

        logger.success(`已添加群组: ${topic}`);
      }
    } catch (error) {
      logger.fail("设置群组失败:", error);
    }
  }

  getContext(roomId, userId) {
    const key = `${roomId}-${userId}`;
    return this.conversations.get(key) || [];
  }

  saveContext(roomId, userId, context) {
    const key = `${roomId}-${userId}`;
    if (context.length > config.bot.contextMessageCount) {
      context = context.slice(-config.bot.contextMessageCount);
    }
    this.conversations.set(key, context);
  }

  clearContext(roomId, userId) {
    const key = `${roomId}-${userId}`;
    this.conversations.delete(key);
  }

  async sendResponse(room, sender, text) {
    try {
      if (!text) {
        logger.warn("回复内容为空");
        return;
      }

      const senderName = sender.name();
      const maxLength = config.bot.maxMessageLength || 500;
      const segments = this.splitTextIntoSegments(text, maxLength);

      for (let i = 0; i < segments.length; i++) {
        const prefix = i === 0 ? `@${senderName}\n` : "";
        await this.messageQueue.add(room, prefix + segments[i]);
      }
    } catch (error) {
      logger.fail("发送回复失败:", error, {
        room: room?.id,
        sender: sender?.name(),
        textLength: text?.length,
      });
      await this.messageQueue.add(room, "抱歉，发送消息失败，请稍后再试。");
    }
  }

  splitTextIntoSegments(text, maxLength) {
    const segments = [];
    for (let i = 0; i < text.length; i += maxLength) {
      segments.push(text.slice(i, i + maxLength));
    }
    return segments;
  }

  async getStats(room) {
    try {
      const roomId = await room.id;
      const config = this.groupConfigs.get(roomId);
      const memberCount = await room.memberAll().then(members => members.length);

      let roomContextCount = 0;
      for (const [key] of this.conversations) {
        if (key.startsWith(roomId)) {
          roomContextCount++;
        }
      }

      return `群名称: ${config.name}
  成员数量: ${memberCount}
  活跃对话: ${roomContextCount}
  总对话数: ${this.conversations.size}
  运行状态: ${this.isRunning ? "正常" : "异常"}
  当前限制: ${config.rateLimit.count}/${config.rateLimit.maxPerMinute}次/分钟`;
    } catch (error) {
      logger.fail("获取统计信息失败:", error);
      return "获取统计信息失败";
    }
  }

  async handleError(error) {
    logger.fail("机器人错误:", {
      message: error.message,
      stack: error.stack,
      time: new Date().toISOString(),
    });

    if (error.message.includes("login") || error.message.includes("认证")) {
      await this.restart();
    }
  }

  async restart() {
    try {
      logger.success("正在重启机器人...");
      this.isRunning = false;
      await this.bot.stop();
      await new Promise(resolve => setTimeout(resolve, 5000));
      await this.start();
    } catch (error) {
      logger.fail("重启失败:", error);
      setTimeout(() => this.restart(), 30000);
    }
  }

  async start() {
    try {
      await this.bot.start();
      logger.success("机器人启动成功");
    } catch (error) {
      logger.fail("启动失败:", error);
      setTimeout(() => this.start(), 30000);
    }
  }
}

class MessageQueue {
  constructor() {
    this.queue = [];
    this.processing = false;
  }

  async add(room, message) {
    this.queue.push({ room, message });
    if (!this.processing) {
      this.process();
    }
  }

  async process() {
    this.processing = true;
    while (this.queue.length > 0) {
      const { room, message } = this.queue.shift();
      try {
        await room.say(message);
        await new Promise(resolve => setTimeout(resolve, 1000));
      } catch (error) {
        logger.fail("发送消息失败", error);
      }
    }
    this.processing = false;
  }
}

export default new WeChatBot();
